package com.own.business.wallet.business.util;

import com.own.business.wallet.business.entity.WalletOrderNoInfo;
import com.own.component.store.core.Store;
import com.own.component.util.time.LocalDateTimeUtil;
import com.own.component.util.time.SecondUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.time.Duration;
import java.util.UUID;

/**
 * OrderGenerateUtil
 * <p>
 * 订单号生成工具（21位订单号）
 *
 * @author chenxueli
 * @date 2023-06-05 14:26:00
 */
@Slf4j
@Component
public class WalletOrderNoGenerateUtil {

    /**
     * 订单时间信息
     */
    private static final String DATE_FORMATTER = "yyyyMMddHH";
    /**
     * 订单号前缀
     */
    private static final String ORDER_PREFIX = "BAL";
    /**
     * 订单缓存编号key
     */
    private static final String ORDER_NUMBER_KEY = "w:o:count";

    @Resource
    private Store<String> store;

    /**
     * 处理订单号信息
     *
     * @param orderNo 原始订单号
     * @return 处理后的订单号
     */
    public static String handler(String orderNo) {
        return "wallet:" + orderNo;
    }

    /**
     * 解析订单号信息
     *
     * @param orderNo 订单号
     * @return 原始订单号
     */
    public static WalletOrderNoInfo resolve(String orderNo) {
        try {
            return new WalletOrderNoInfo(orderNo);
        } catch (Exception e) {
            throw new IllegalArgumentException("订单号格式错误");
        }
    }

    /**
     * 获取编号（三十六进制）
     *
     * @param count 获取数量
     * @return 编号
     */
    private String getNumber(int count) {
        // 获取今天剩余时间秒
        var expire = SecondUtil.todayDuration();
        // 根据获取自增序号
        var number = store.atomic().getAndIncrement(ORDER_NUMBER_KEY, Duration.ofSeconds(expire));
        // 补充位数（使用4位25进制的数据，满足每小时9765625条数据）,使用36进制可以满足60466175条数据
        var text = StringUtils.leftPad(Long.toString(number, 36), count, "0");
        return text.length() > count ? text.substring(0, count) : text;
    }

    /**
     * 生成订单号（32位）
     * <p>
     * 订单前缀号（3） + 订单类型（1） + 日期（10） + 自增序号（7） + 随机字符串（11）
     *
     * @param type 订单类型{@link com.own.business.pay.common.constant.ConstantPay.Type} 1=收入 2=支付 3=退款
     * @return 订单号
     */
    public String get(int type) {
        var count = 7;
        return (ORDER_PREFIX + type + LocalDateTimeUtil.format(DATE_FORMATTER) + getNumber(count) + UUID.randomUUID().toString().replaceAll("-", "").substring(0, 11)).toUpperCase();
    }

}
